package com.ac.scum.log.task.task;

import com.ac.scum.config.bean.ServerConfigRestart;
import com.ac.scum.player.score.bean.PlayerScoreOnline;
import com.ac.scum.log.bean.Server;
import com.ac.scum.log.task.mapper.player.PlayerScoreOnlineMapper;
import com.ac.scum.log.task.mapper.server.ServerConfigRestartMapper;
import com.ac.scum.log.task.service.ServerService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Set;

@Slf4j
@Service
@RequiredArgsConstructor
public class PlayerLogoutInTheServerRestart {
    private final ServerService serverService;
    private final RedisTemplate<String, Object> redisTemplate;
    private final PlayerScoreOnlineMapper playerScoreOnlineMapper;
    private final ServerConfigRestartMapper serverConfigRestartMapper;

    @Scheduled(cron = "0/2 * * * * ?")
    @Transactional
    public void inTheServerRestartOfflinePlayer() {
        List<Server> servers = serverService.getServersWithSpecifiedPackageIds(1L);
        if (!servers.isEmpty()) {
            for (Server server : servers) {
                List<ServerConfigRestart> serverConfigRestarts = serverConfigRestartMapper.selectList(Wrappers.<ServerConfigRestart>lambdaQuery().eq(ServerConfigRestart::getServerId, server.getId()));
                if (serverConfigRestarts.isEmpty()) {
                    continue;
                }
                for (ServerConfigRestart serverConfigRestart : serverConfigRestarts) {
                    String restartLockKey = "playerLogoutInTheServerRestart::" + serverConfigRestart.getServerId();
                    if (serverConfigRestart.getRestartTime().isAfter(LocalTime.now().minusMinutes(5))
                            && serverConfigRestart.getRestartTime().isBefore(LocalTime.now().plusMinutes(5))
                            && Boolean.FALSE.equals(redisTemplate.hasKey(restartLockKey))) {
                        redisTemplate.opsForValue().set(restartLockKey, Boolean.TRUE, 5, java.util.concurrent.TimeUnit.MINUTES);
                        String redisHashKey = "online_time:" + server.getId();
                        Set<Object> keys = redisTemplate.opsForHash().keys(redisHashKey);
                        for (Object key : keys) {
                            PlayerScoreOnline playerScoreOnline = (PlayerScoreOnline) redisTemplate.opsForHash().get(redisHashKey, key);
                            if (playerScoreOnline == null) {
                                log.warn("玩家 {} 任务下线出现异常，未知数据", key);
                                continue;
                            }
                            playerScoreOnline.setLogoutTime(LocalDateTime.now());
                            Duration duration = Duration.between(playerScoreOnline.getLoginTime(), playerScoreOnline.getLogoutTime());
                            playerScoreOnline.setOnlineTime(duration.toMinutes());
                            playerScoreOnlineMapper.insert(playerScoreOnline);
                            redisTemplate.opsForHash().delete(redisHashKey, key);
                        }
                        log.info("服务器 {} 在线玩家任务下线: {} 个", server.getId(), keys.size());
                    }
                }
            }
        }
    }
}
